package edu.hznu.retroSnakerPlanServer.service.imp;

import edu.hznu.retroSnakerPlanServer.entity.*;
import edu.hznu.retroSnakerPlanServer.service.PlayerService;

import java.util.*;

/**
 * create by Cliven on 2018-06-01 14:19
 * 实现了玩家信息的操作
 */
public class PlayerServiceImpl implements PlayerService {

    private GameContext context;
    private Random random;

    private void PlayerServiceImpl() {
    }

    public PlayerServiceImpl(GameContext context) {
        this.context = context;
        this.random = new Random();
    }

    /**
     * 获取区域内的所有玩家
     *
     * @param area 区域
     * @return 区域内的所有玩家
     * @author Cliven
     * @since 2018-6-1 20:15:25
     */
    @Override
    public synchronized List<Player> getAreaPlayer(Area area) {
        // 遍历所有游戏玩家
        Area playerArea = null;
        boolean isInArea = false;
        Integer areaDx = area.ex - area.sx;
        Integer areaDy = area.ey - area.sy;

        double areaR = Math.sqrt((areaDx / 2.0) * (areaDx / 2.0) + (areaDy / 2.0) * (areaDy / 2.0));

        Integer playerAreaDx = 0;
        Integer playerAreaDy = 0;
        double playerAreaR = 0.0;

        double areaX = area.sx + areaDx / 2;
        double areaY = area.sy = areaDy / 2;

        double playerAreaX = 0.0;
        double playerAreaY = 0.0;

        double distance = 0;

        List<Player> areaPlayers = new LinkedList<>();
        for (Player player : context.getPlayers().values()) {
            playerArea = player.getArea();
            playerAreaDx = playerArea.ex - playerArea.sx;
            playerAreaDy = playerArea.ey - playerArea.sy;
            playerAreaR = Math.sqrt((playerAreaDx / 2.0) * (playerAreaDx / 2.0) + (playerAreaDy / 2.0) * (playerAreaDy / 2.0));

            playerAreaX = playerArea.sx + playerAreaDx / 2;
            playerAreaY = playerArea.sy = playerAreaDy / 2;

            distance = Math.sqrt((playerAreaX - areaX) * (playerAreaX - areaX) + (playerAreaY - areaY) * (playerAreaY - areaY));
            if (distance <= (playerAreaR + areaR)) {
                areaPlayers.add(player);
            }
        }
        return areaPlayers;
    }

    /**
     * 创建玩家
     *
     * @return 新玩家信息
     * @author Cliven
     * @since 2018-06-01 14:06:24
     */
    @Override
    public synchronized Player create() {
        // 生成ID
        Integer id = createId();
        // 生成身体
        List<SnakeNode> snake = createSnake(id);
        Player player = new Player(snake, 0);
        return add(player);
    }

    /**
     * 新增玩家
     *
     * @param player 玩家
     * @return 加入的玩家
     * @author Cliven
     * @since 2018-06-04 11:14:05
     */
    @Override
    public synchronized Player add(Player player) {
        Map<Integer, Player> playerMap = context.getPlayers();
        playerMap.put(player.getId(), player);
        return playerMap.get(player.getId());
    }

    /**
     * 生成用户id
     *
     * @return 用户ID
     * @author Cliven
     * @since 2018-06-01 15:40:50
     */
    private Integer createId() {
        Map<Integer, Player> playerMap = context.getPlayers();
        if (playerMap.entrySet().size() >= context.getMaxPlayerNumber()) {
            throw new IllegalArgumentException("Can't create a role beyond the maximum number of players");
        }
        int id = -1;
        for (Integer i = 1; i < 127; i++) {
            if (playerMap.get(i) == null) {
                id = i;
                break;
            }
        }
        if (id == -1) {
            throw new IllegalArgumentException("Can't create a role unknown error");
        }
        return id;
    }

    /**
     * 创建玩家角色
     *
     * @param id 玩家ID
     * @return 玩家角色链表
     * @author Cliven
     * @since 2018-06-01 15:40:04
     */
    private List<SnakeNode> createSnake(Integer id) {
        Integer initLen = context.getInitLength();
        List<SnakeNode> list = new ArrayList<>(initLen);
        Integer x = initLen + random.nextInt(context.getWidth() - initLen * 2);
        Integer y = initLen + random.nextInt(context.getHeight() - initLen * 2);
        Integer direction = random.nextInt(4);
        Integer dx = 0;
        Integer dy = 0;
        switch (direction) {
            case Direction.UP:
                dy = 1;
                break;
            case Direction.DOWN:
                dy = -1;
                break;
            case Direction.LEFT:
                dx = 1;
                break;
            case Direction.RIGHT:
                dx = -1;
                break;
            default:
                break;
        }
        SnakeNode snakeNode = null;
        Integer colorType;
        do {
            colorType = random.nextInt(ColorType.TYPE_NUMBER);
        } while (colorType == 0);


        for (int i = 0; i < initLen; i++) {
            // 非头结点则需要修改，坐标
            if (i != 0) {
                x += dx;
                y += dy;
            }
            snakeNode = new SnakeNode().setX(x)
                    .setY(y)
                    .setColorType(colorType)
                    .setId(id)
                    .setDirection(direction);
            list.add(snakeNode);
        }
        return list;
    }

    /**
     * 移除玩家
     *
     * @param id 玩家ID
     * @return 被移除的玩家信息
     * @author Cliven
     * @since 2018-06-01 14:07:31
     */
    @Override
    public synchronized Player remove(Integer id) {
        Map<Integer, Player> playerMap = context.getPlayers();
        return playerMap.remove(id);
    }

    /**
     * 更新玩家信息
     *
     * @param player 要更新的玩家信息
     * @return 更新后的玩家信息
     * @author Cliven
     * @since 2018-06-01 14:09:07
     */
    @Override
    public synchronized Player update(Player player) {
        Map<Integer, Player> playerMap = context.getPlayers();
        player.setLastUpdateTime(System.currentTimeMillis());
        return playerMap.put(player.getId(), player);
    }

    /**
     * 查找玩家信息
     *
     * @param id 玩家ID
     * @return 空/玩家信息
     * @author Cliven
     * @since 2018-06-01 14:11:22
     */
    @Override
    public synchronized Player findById(Integer id) {
        return context.getPlayers().get(id);
    }
}
